#include "String.h"
#include "StringBuffer.h"
#include "StringCreator.h"

String::String()
{
	init(new uchar[0]);

	offset  = 0;
	count   = 0;
}

String::String(const ToStringConvertible& in)
{
	ToStringConvertible* tmp = (ToStringConvertible*)(void *)&in;
	String sin = tmp->toString();

	offset   = sin.offset;
	count    = sin.count;

	assign(sin);
}

String::String(uchar* val, natural s)
{
	init(val);

	offset  = 0;
	count   = s;
}

String::~String()
{

}

String::String(const String& in)
{
	assign(in);
	offset   = in.offset;
	count    = in.count;
}

String String::operator=(const String& in)
{
	unreference();
	assign(in);

	offset   = in.offset;
	count    = in.count;

	return *this;
}

bool String::equals(const String& in)
{
	uchar* value = getManagedMemoryData();
	uchar* invalue = ((String*)(void*)&in)->getManagedMemoryData();

	if(count != in.count) return false;

	for(natural i = 0; i < count; i++)
		if(value[i + offset] != invalue[i + in.offset])
			return false;

	return true;
}

bool String::operator==(const String& in)
{
	return equals(in);
}

bool String::operator!=(const String& in)
{
	return !equals(in);
}

uchar String::operator[](natural i)
{
	if(i >= count)
		throw L"Index out of Bounds";

	return getManagedMemoryData()[offset + i];
}

bool String::startsWith(const String& prefix, natural toffset)
{
	uchar *ta = getManagedMemoryData();
	uchar *pa = ((String*)(void*)&prefix)->getManagedMemoryData();

	natural to = offset + toffset;
	natural po = prefix.offset;
	natural pc = prefix.count;

	// Note: toffset might be near -1>>>1.
	if (pc > count || toffset > count - pc)
		{return false;}

	pc++;
	while (--pc >= 1)
	{
		if (ta[to++] != pa[po++])
			{return false;}
	}

	return true;
}

StringBuffer String::operator*()
{
	StringBuffer r;

	r += *this;

	return r;
}
